<template>
  <div class="game-container">
    <canvas ref="canvas" :width="canvasSize" :height="canvasSize"></canvas>
    <div class="score-board">得分：{{ score }}</div>
    <div v-if="!isPlaying" class="start-prompt">按空格键开始游戏</div>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, onUnmounted } from 'vue';
const canvas = ref(null);  // 添加这行声明，解决canvas未定义的问题，Vue3.0中需要声明ref
const gridSize = 20;
const canvasSize = ref(400);
const tileCount = canvasSize.value / gridSize;

const ctx = ref(null);
const gameLoop = ref(null);
const isPlaying = ref(false);
const score = ref(0);
const gameSpeed = ref(100);

const state = reactive({
  snake: [{ x: 10, y: 10 }],
  food: { x: 15, y: 15 },
  direction: { dx: 0, dy: 0 }
});

const generateFood = () => {
  do {
    state.food.x = Math.floor(Math.random() * tileCount);
    state.food.y = Math.floor(Math.floor(Math.random() * tileCount));
  } while (state.snake.some(segment => segment.x === state.food.x && segment.y === state.food.y));
};

const checkCollision = () => {
  const head = state.snake[0];
  return (
    head.x < 0 || head.x >= tileCount ||
    head.y < 0 || head.y >= tileCount ||
    state.snake.slice(1).some(segment => segment.x === head.x && segment.y === head.y)
  );
};

const updateGame = () => {
  const head = {
    x: state.snake[0].x + state.direction.dx,
    y: state.snake[0].y + state.direction.dy
  };

  state.snake.unshift(head);

  if (head.x === state.food.x && head.y === state.food.y) {
    score.value += 10;
    if (score.value % 50 === 0) {
      gameSpeed.value *= 0.8;
      resetGameLoop();
    }
    generateFood();
  } else {
    state.snake.pop();
  }

  if (checkCollision()) {
    gameOver();
    return;
  }

  draw();
};

const draw = () => {
  ctx.value.fillStyle = 'white';
  ctx.value.fillRect(0, 0, canvasSize.value, canvasSize.value);

  // 绘制蛇
  ctx.value.fillStyle = '#4CAF50';
  state.snake.forEach(segment => {
    ctx.value.fillRect(
      segment.x * gridSize,
      segment.y * gridSize,
      gridSize - 2,
      gridSize - 2
    );
  });

  // 绘制食物
  ctx.value.fillStyle = 'red';
  ctx.value.fillRect(
    state.food.x * gridSize,
    state.food.y * gridSize,
    gridSize - 2,
    gridSize - 2
  );
};

const resetGameLoop = () => {
  if (gameLoop.value) clearInterval(gameLoop.value);
  gameLoop.value = setInterval(updateGame, gameSpeed.value);
};

const gameOver = () => {
  clearInterval(gameLoop.value);
  isPlaying.value = false;
};

const handleKeyPress = (e) => {
  if (e.code === 'Space' && !isPlaying.value) {
    startGame();
    return;
  }

  switch(e.key) {
    case 'ArrowUp':
      if (state.direction.dy !== 1) {
        state.direction = { dx: 0, dy: -1 };
      }
      break;
    case 'ArrowDown':
      if (state.direction.dy !== -1) {
        state.direction = { dx: 0, dy: 1 };
      }
      break;
    case 'ArrowLeft':
      if (state.direction.dx !== 1) {
        state.direction = { dx: -1, dy: 0 };
      }
      break;
    case 'ArrowRight':
      if (state.direction.dx !== -1) {
        state.direction = { dx: 1, dy: 0 };
      }
      break;
  }
};

const startGame = () => {
  isPlaying.value = true;
  score.value = 0;
  gameSpeed.value = 100;
  state.snake = [{ x: 10, y: 10 }];
  state.direction = { dx: 0, dy: 0 };
  generateFood();
  resetGameLoop();
};

onMounted(() => {
  ctx.value = canvas.value.getContext('2d');
  window.addEventListener('keydown', handleKeyPress);
});

onUnmounted(() => {
  window.removeEventListener('keydown', handleKeyPress);
  if (gameLoop.value) clearInterval(gameLoop.value);
});
</script>

<style scoped>
.game-container {
  position: relative;
  display: inline-block;
}

canvas {
  border: 2px solid #4CAF50;
  border-radius: 5px;
}

.score-board {
  position: absolute;
  top: 10px;
  right: 10px;
  font-size: 24px;
  color: #4CAF50;
  font-weight: bold;
  text-shadow: 1px 1px 2px rgba(0,0,0,0.3);
}

.start-prompt {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: 24px;
  color: #4CAF50;
  font-weight: bold;
  text-shadow: 1px 1px 2px rgba(0,0,0,0.3);
}
</style>